package impl

import (
	"context"
	"time"

	"gitee.com/go-course/go12/devcloud-mini/cmdb/apps/resource"
	"gitee.com/go-course/go12/devcloud-mini/cmdb/apps/secret"
	"gitee.com/go-course/go12/devcloud-mini/cmdb/provider"
	"gitee.com/go-course/go12/devcloud-mini/cmdb/provider/tencent"
	"github.com/infraboard/mcube/exception"
	"github.com/infraboard/mcube/ioc/config/application"
	"go.mongodb.org/mongo-driver/bson"
)

func (i *impl) CreateSecret(
	ctx context.Context,
	in *secret.CreateSecretRequest,
) (*secret.Secret, error) {
	i.log.Debug().Msgf("save secret ...")

	// 请求的校验
	if err := i.validator.Struct(in); err != nil {
		return nil, exception.NewBadRequest(err.Error())
	}

	// 构建secret对象
	ins := secret.NewSecret(in)

	err := ins.Encrypt(application.App().EncryptKey)
	if err != nil {
		return nil, err
	}

	// 入库
	// 加密
	if _, err := i.col.InsertOne(ctx, ins); err != nil {
		return nil, err
	}

	return ins, nil
}

// 查询secret
func (i *impl) DescribeSecret(
	ctx context.Context,
	in *secret.DescribeSecretRequest) (
	*secret.Secret, error) {
	ins := secret.NewSecret(nil)
	err := i.col.FindOne(ctx, bson.M{"_id": in.Id}).Decode(ins)
	if err != nil {
		return nil, err
	}

	// 解密
	if err := ins.Decrypt(application.App().EncryptKey); err != nil {
		return nil, err
	}

	return ins, nil
}

// 使用云商凭证同步资源 Stream
func (i *impl) SyncResource(
	ctx context.Context,
	in *secret.SyncResourceRequest,
	hook secret.SyncResourceHandler) error {

	// 1. 查询出Secret
	ins, err := i.DescribeSecret(ctx, &secret.DescribeSecretRequest{Id: in.Id})
	if err != nil {
		return err
	}

	// 2. 使用secret 创建一个 resource provider
	// 3. 使用这个 provider 来进行资源同步
	for _, rt := range ins.Spec.ResourceTypes {
		switch rt {
		// tencent:an
		case resource.TYPE_HOST:
			for _, region := range ins.Spec.Regions {
				//
				rp := tencent.NewClient(ins.Spec.Key, ins.Spec.Value, region).CVMProvider()
				rp.Sync(ctx, &provider.SyncRequest{}, func(r *resource.Resource) {
					if r == nil {
						hook(&secret.SyncResponse{
							Error: "no resource sync",
						})
						return
					}

					// 资源额外信息补充
					r.Meta.Domain = ins.Domain
					r.Meta.Namespace = ins.Namespace
					r.Meta.SyncAt = time.Now().Unix()

					// 4. 使用将同步完成的资源 写入resource 模块
					if _, err := i.resource.Save(ctx, r); err != nil {
						hook(&secret.SyncResponse{
							Id:    r.Meta.Id,
							Name:  r.Spec.Name,
							Error: err.Error(),
						})
					} else {
						hook(&secret.SyncResponse{
							Id:   r.Meta.Id,
							Name: r.Spec.Name,
						})
					}
				})
			}

		}
	}

	return nil
}
